SuggestBox = function (config, payload){
    let suggestBox = config.rootDom;
    let activeClass = config.activeClass;

    let active = null;
    let isShowing = false;
    let onChange = config.onChange?config.onChange:function(oldDom, newDom){};
    let onSelected = config.onSelected?config.onSelected:function (selected){};
    function hide(){
        if (!isShowing){
            return;
        }
        isShowing = false;
        if (active !== null){
            $(active).removeClass(activeClass);
        }
        active = null;
        $(suggestBox).animate({"opacity":0}, 500, 'swing', function(){
            $(suggestBox).css("display", "none");
        });
    }
    function show(){
        if (isShowing){
            return;
        }
        isShowing = true;
        $(suggestBox).animate({"opacity":1});
        $(suggestBox).css("display", "block");
    }

    function changeActive( dom ){
        if (!isShowing){
            return;
        }
        if ($(active) !== $(dom)){
            if (active !== null){
                $(active).removeClass(activeClass);
            }
            $(dom).addClass(activeClass);
            onChange(active, dom);
            active = dom;
        }
    }
    $(suggestBox).delegate(".suggestItem", "mouseover", function(e){
        changeActive($(e.currentTarget));
    });

    $(suggestBox).delegate(".suggestItem", "click", function(e){
        onSelected($(e.currentTarget));
        hide();
    })
    window.onkeydown = function(e){
        let newActive = $(active);
        let findActive = null;
        // 上
        if (e.keyCode === 38){
            newActive = $(active).prev();
            findActive = ":last-child";
        }
        // 下
        if (e.keyCode === 40){
            newActive = $(active).next();
            findActive = ":first-child";
        }
        if (null != findActive){
            if (newActive.length == 0){
                newActive = $(suggestBox).find(".suggestItem" + findActive);
            }
            changeActive(newActive);
        }
    }
    if (payload !== undefined && payload != null){
        payload.hide = hide;
        payload.show = show;
    }
};
function Cache(maxsize, lastVisited, cache) {
    var c = {};
    var size = 0;
    // 定时清理无效数据
    setInterval(clear, 200);
    function clear() {
        for (var key in c) {
            var item = c[key];
            if (verify(item)) {
                continue;
            }
            size --;
            delete c[key];
        }
    }

    function verify(item) {
        var now = Date.now();
        if (cache > 0 && now - item.cacheTime > cache) {
            return false;
        }
        if (lastVisited > 0 && now - item.lastVisited > lastVisited) {
            return false;
        }
        return true;
    }

    function remove() {
        if (size < maxsize) {
            return;
        }
        // 优先清理无效数据
        clear();
        if (size < maxsize) {
            return;
        }
        // 随机清除数据
        for (var key in c) {
            if (size - maxsize <= 0) {
                return;
            }
            size--;
            delete c[key];
        }
    }

    return {
        getIfPresent: function (key) {
            var item = c[key];
            if (item === null || item === undefined) {
                return null;
            }
            var now = Date.now();
            if (!verify(item)) {
                return null;
            }
            item.lastVisited = now;
            return c[key].data;
        },
        get: function (key, getter) {
            var v = this.get(key);
            if (v == null) {
                v = getter(key);
                this.put(key, v);
            }
            return v;
        },
        put: function(key, val) {
            if (!c[key]) {
                size++;
                remove();
            }
            var now = Date.now();
            c[key] = {data: val, cacheTime: now, lastVisited: now};
        },
        invalid: function(key) {
            var item = c[key];
            if (!item) {
                return;
            }
            item.cacheTime = 0;
            item.lastVisited = 0;
        }
    }
}
SuggestBox.suggest = function(key, successFunc){
    function isNull(o) {
        return o === null || o === undefined;
    }
    if (!successFunc){
        successFunc = SuggestBox._successFunc_?SuggestBox._successFunc_:function(){};
    }
    else{
        SuggestBox._successFunc_ = successFunc;
    }
    if (!SuggestBox._no_){
        SuggestBox._no_ = 0;
    }

    var _this = this;
    if (isNull(this.cache)) {
        // 缓存最大200条，2小时有效
        this.cache = new Cache(200, -1, 7200000)
    }
    var cache = this.cache.getIfPresent(encodeURI(key));
    console.log(cache);
    if (cache !== null) {
        successFunc(cache);
        return ;
    }
    if (!isNull(this.interval)) {
        clearInterval(this.interval);
    }
    this.interval = setTimeout(()=>{
        $.get("/api/suggest" , {key: key, no: ++SuggestBox._no_}, function (result){
            if (result.code != 0){
                return;
            }
            var data = result.data;
            if (SuggestBox._no_ != data.no){
                return;
            }
            _this.cache.put(data.key, data.list);
            successFunc(data.list);
        })
    }, 500);
}

Search = function(config, payload){
    let dom = config.dom;
    let submit = config.submit?config.submit:function(){};
    let onFocus = config.focus?config.focus:function (){};
    let onBlur = config.blur?config.blur:function (){};
    let onInput = config.input?config.input:function (){};
    $(dom).focus(onFocus);
    $(dom).blur(onBlur);
    $(dom).on("input", onInput);
    function text(content){
        if (undefined === content){
            return $(dom).val();
        }
        $(dom).val(content);
    }
    function search(content){
        if (content === undefined || content === null){
            content = text();
        }
        if (content === undefined || content === null || "" === content){
            return;
        }
        text(content);
        submit(content);
    }
    $(dom).on("keydown", function(ev){
        if( ev.keyCode == 13){
            submit(text());
        };
    })
    if (payload !== undefined && payload != null){
        payload.text = text;
        payload.search = search;
        payload.submit = submit;
    }
}